JAVA ReflectUtils 发表于 1900-01-09 | 分类于 JAVA | 相关文章:Java RelfectJava RelfectUtils反射一:基本类周边信息获取反射二:泛型相关周边信息获取反射三:类内部信息获取 Invoking Arbitrary Methods:12Method sqrt = Math.class.getMethod("sqrt", double.class);double x = (Double) sqrt.invoke(null, 100); // 此方法为静态方法,隐式参数为null ReflectionUtils:123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306package com.xian.reflection;import java.lang.annotation.Annotation;import java.lang.reflect.AccessibleObject;import java.lang.reflect.Array;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import java.util.ArrayList;/** * ReflectionUtils : * 1 Get all features of a class * 2 A generic toString method that works for any class * 3 Copy array * * @author xianxiaotao */public class ReflectionUtils { /** * flag to contain annotation and exception string */ private static int flag = 0b00000000_00000000_00000000_00000000; /** * flag : contain annotation string */ public static final int CONTAIN_ANNOTATION = 0b00000000_00000000_00000000_00000001; /** * flag : contain exception string */ public static final int CONTAIN_EXCEPTION = 0b00000000_00000000_00000000_00000010; // Cycles of references could cause an infinite recursion. Therefore, // the ObjectAnalyzer keeps track of objects that were already visited private static ArrayList<Object> visited = new ArrayList<>(); // Suppresses default constructor, ensuring non-instantiability. private ReflectionUtils() {} /** * Get all features of a class * @param className * @return * @throws ClassNotFoundException */ public static String getClass(String className) throws ClassNotFoundException { StringBuilder sb = new StringBuilder(); Class<?> clazz = Class.forName(className); Class<?> superClazz = clazz.getSuperclass(); sb.append(clazz.getPackage().getName()).append("\n\n"); sb.append(getAnnotations(clazz.getDeclaredAnnotations())); sb.append(getModifiers(clazz.getModifiers())); sb.append("class ").append(className); if (superClazz != null && superClazz != Object.class) sb.append(" extends ").append(superClazz.getName()); Class<?>[] interfaces = clazz.getInterfaces(); if (interfaces.length > 0) sb.append(" implements "); for (int i = 0; i < interfaces.length; i++) { if (i > 0) sb.append(", "); sb.append(interfaces[i].getName()); } sb.append(" {\n"); sb.append(getConstructors(clazz)).append("\n"); sb.append(getMethods(clazz)).append("\n"); sb.append(getFields(clazz)).append("\n"); sb.append("}\n"); return sb.toString(); } /** * Get all constructors * @param clazz * @return String */ public static String getConstructors(Class<?> clazz) { StringBuilder sb = new StringBuilder(); Constructor<?>[] constructors = clazz.getDeclaredConstructors(); for (Constructor<?> c : constructors) { sb.append(getAnnotations(c.getDeclaredAnnotations())); String name = c.getName(); sb.append(" "); String modifiers = Modifier.toString(c.getModifiers()); if (modifiers.length() > 0) sb.append(modifiers).append(" "); sb.append(name).append("("); String paramStr = getParamTypes(c.getParameterTypes()); sb.append(paramStr).append(")"); sb.append(getExceptions(c.getExceptionTypes())); sb.append(";\n"); } return sb.toString(); } private static String getExceptions(Class<?>[] es) { StringBuilder sb = new StringBuilder(); if (isContainException() && es != null && es.length > 0) { sb.append(" throws "); for (int i = 0; i < es.length; i++) { if (i > 0) sb.append(", "); sb.append(es[i].getName()); } } return sb.toString(); } /** * get annotation of a class, method or field * @param as * @return */ private static String getAnnotations(Annotation[] as) { StringBuilder sb = new StringBuilder(); if (isContainAnnotation() && as != null && as.length > 0) { sb.append(" @"); for (int i = 0; i < as.length; i++) { sb.append(as[i].annotationType().getName()).append("\n"); } } return sb.toString(); } /** * get parameter types * @param paramTypes * @return */ private static String getParamTypes(Class<?>[] paramTypes) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < paramTypes.length; i++) { if (i > 0) sb.append(", "); sb.append(paramTypes[i].getName()); } return sb.toString(); } private static String getModifiers(int modifier) { String modifiers = Modifier.toString(modifier); if (modifiers.length() > 0) return modifiers + " "; return ""; } /** * Get all methods of a class * @param clazz * @return */ public static String getMethods(Class<?> clazz) { return getMethods(clazz, null); } /** * Gets the method for the specified method name * @param clazz * @return */ public static String getMethods(Class<?> clazz, String methodName) { StringBuilder sb = new StringBuilder(); Method[] methods = clazz.getDeclaredMethods(); for (Method m : methods) { sb.append(getAnnotations(m.getDeclaredAnnotations())); Class<?> returnType = m.getReturnType(); String name = m.getName(); if (methodName != null && !methodName.equals(name)) continue; sb.append(" ").append(getModifiers(m.getModifiers())).append(returnType.getName()).append(" " + name + "("); String paramStr = getParamTypes(m.getParameterTypes()); sb.append(paramStr).append(")"); sb.append(getExceptions(m.getExceptionTypes())); sb.append(";\n"); } return sb.toString(); } /** * Get all fields of a class * @param clazz * @return */ public static String getFields(Class<?> clazz) { StringBuilder sb = new StringBuilder(); Field[] fields = clazz.getDeclaredFields(); for (Field f : fields) { Class<?> type = f.getType(); sb.append(" ").append(getModifiers(f.getModifiers())).append(type.getName()).append(" ").append(f.getName()).append(";\n"); } return sb.toString(); } /** * ReflectionUtils.setFlag(ReflectionUtils.CONTAIN_EXCEPTION | ReflectionUtils.CONTAIN_ANNOTATION); * @param state */ public static void setFlag(int state) { flag = state; } private static boolean isContainException() { return (flag & CONTAIN_EXCEPTION) == CONTAIN_EXCEPTION ? true : false; } private static boolean isContainAnnotation() { return (flag & CONTAIN_ANNOTATION) == CONTAIN_ANNOTATION ? true : false; } /** * Converts an object to a string representation that lists all fields. * @param obj * @return a string with the object's class name and all field names and values */ public static String toString(Object obj) { if (obj == null) return "null"; if (visited.contains(obj)) return "..."; visited.add(obj); Class<?> clazz = obj.getClass(); if (clazz == String.class) return (String) obj; if (clazz.isArray()) { String r = clazz.getComponentType() + "[]{"; for (int i = 0; i < Array.getLength(obj); i++) { if (i > 0) r += ","; Object val = Array.get(obj, i); if (clazz.getComponentType().isPrimitive()) r += val; else r += toString(val); // recursion } return r + "}"; } // others : inspect the fields of this class and all superclasses String r = clazz.getName(); do { r += " ["; Field[] fields = clazz.getDeclaredFields(); AccessibleObject.setAccessible(fields, true); // uses the setAccessible convenience method to make all fields accessible for (Field f : fields) { // get the names and values of all fields if (!Modifier.isStatic(f.getModifiers())) { if (!r.endsWith("[")) r += ","; r += f.getName() + "="; try { Class<?> t = f.getType(); Object val = f.get(obj); if (t.isPrimitive()) r += val; else r += toString(val); } catch (Exception e) { e.printStackTrace(); } } } r += "]"; clazz = clazz.getSuperclass(); if (clazz.getSuperclass() != Object.class) clazz = null; } while (clazz != null); return r; } /** * This method grows an array by allocating a new array of the same type and copying all elements. * @param a the array to grow. This can be an object array or a primitive type array * @return a larger array that contains all elements of a. */ public static Object copyOf(Object arr, int newLength) { Class<?> clazz = arr.getClass(); if (!clazz.isArray()) return null; Class<?> componentType = clazz.getComponentType(); int length = Array.getLength(arr); Object newArray = Array.newInstance(componentType, newLength); System.arraycopy(arr, 0, newArray, 0, Math.min(length, newLength)); return newArray; } // clear static ArrayList var(visited) public static void clean() { visited.clear(); } // unit test public static void main(String[] args) throws ClassNotFoundException { // setFlag(CONTAIN_EXCEPTION | CONTAIN_ANNOTATION); // System.out.println(getClass("java.lang.String")); /* // 使用方式如下或者在自定义类中toString方法里添加 ReflectionUtils.clear(); return ReflectionUtils.toString(this); ArrayList<Integer> squares = new ArrayList<>(); for (int i = 1; i <= 5; i++) squares.add(i * i); System.out.println(ReflectionUtils.toString(squares)); ReflectionUtils.clear(); */ System.out.println(new Manager("xian xiaotao", 300000, 2020, 1, 1)); // com.xian.reflection.Manager [name=xian xiaotao, salary=300000.0, hireDay=2020-01-01] // com.xian.reflection.Manager [bonus=0.0] [id=0,name=xian xiaotao,salary=300000.0,hireDay=java.time.LocalDate [year=2020,month=1,day=1]] }} 输出:123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108java.langpublic final class java.lang.String implements java.io.Serializable, java.lang.Comparable, java.lang.CharSequence { public java.lang.String([B, int, int); public java.lang.String([B, java.nio.charset.Charset); public java.lang.String([B, java.lang.String) throws java.io.UnsupportedEncodingException; public java.lang.String([B, int, int, java.nio.charset.Charset); public java.lang.String([B, int, int, java.lang.String) throws java.io.UnsupportedEncodingException; java.lang.String([C, boolean); public java.lang.String(java.lang.StringBuilder); public java.lang.String(java.lang.StringBuffer); public java.lang.String([B); public java.lang.String([I, int, int); public java.lang.String(); public java.lang.String([C); public java.lang.String(java.lang.String); public java.lang.String([C, int, int); @java.lang.Deprecated public java.lang.String([B, int); @java.lang.Deprecated public java.lang.String([B, int, int, int); public boolean equals(java.lang.Object); public java.lang.String toString(); public int hashCode(); public volatile int compareTo(java.lang.Object); public int compareTo(java.lang.String); public int indexOf(java.lang.String, int); static int indexOf([C, int, int, java.lang.String, int); static int indexOf([C, int, int, [C, int, int, int); public int indexOf(int); public int indexOf(java.lang.String); public int indexOf(int, int); public static java.lang.String valueOf(char); public static java.lang.String valueOf(java.lang.Object); public static java.lang.String valueOf(boolean); public static java.lang.String valueOf([C, int, int); public static java.lang.String valueOf([C); public static java.lang.String valueOf(double); public static java.lang.String valueOf(float); public static java.lang.String valueOf(long); public static java.lang.String valueOf(int); private static void checkBounds([B, int, int); public int length(); public boolean isEmpty(); public char charAt(int); public int codePointAt(int); public int codePointBefore(int); public int codePointCount(int, int); public int offsetByCodePoints(int, int); public void getChars(int, int, [C, int); void getChars([C, int); public [B getBytes(); public [B getBytes(java.lang.String) throws java.io.UnsupportedEncodingException; @java.lang.Deprecated public void getBytes(int, int, [B, int); public [B getBytes(java.nio.charset.Charset); public boolean contentEquals(java.lang.StringBuffer); public boolean contentEquals(java.lang.CharSequence); private boolean nonSyncContentEquals(java.lang.AbstractStringBuilder); public boolean equalsIgnoreCase(java.lang.String); public int compareToIgnoreCase(java.lang.String); public boolean regionMatches(int, java.lang.String, int, int); public boolean regionMatches(boolean, int, java.lang.String, int, int); public boolean startsWith(java.lang.String); public boolean startsWith(java.lang.String, int); public boolean endsWith(java.lang.String); private int indexOfSupplementary(int, int); public int lastIndexOf(int, int); static int lastIndexOf([C, int, int, [C, int, int, int); static int lastIndexOf([C, int, int, java.lang.String, int); public int lastIndexOf(java.lang.String, int); public int lastIndexOf(int); public int lastIndexOf(java.lang.String); private int lastIndexOfSupplementary(int, int); public java.lang.String substring(int); public java.lang.String substring(int, int); public java.lang.CharSequence subSequence(int, int); public java.lang.String concat(java.lang.String); public java.lang.String replace(char, char); public java.lang.String replace(java.lang.CharSequence, java.lang.CharSequence); public boolean matches(java.lang.String); public boolean contains(java.lang.CharSequence); public java.lang.String replaceFirst(java.lang.String, java.lang.String); public java.lang.String replaceAll(java.lang.String, java.lang.String); public [Ljava.lang.String; split(java.lang.String, int); public [Ljava.lang.String; split(java.lang.String); public static transient java.lang.String join(java.lang.CharSequence, [Ljava.lang.CharSequence;); public static java.lang.String join(java.lang.CharSequence, java.lang.Iterable); public java.lang.String toLowerCase(java.util.Locale); public java.lang.String toLowerCase(); public java.lang.String toUpperCase(); public java.lang.String toUpperCase(java.util.Locale); public java.lang.String trim(); public [C toCharArray(); public static transient java.lang.String format(java.util.Locale, java.lang.String, [Ljava.lang.Object;); public static transient java.lang.String format(java.lang.String, [Ljava.lang.Object;); public static java.lang.String copyValueOf([C, int, int); public static java.lang.String copyValueOf([C); public native java.lang.String intern(); private final [C value; private int hash; private static final long serialVersionUID; private static final [Ljava.io.ObjectStreamField; serialPersistentFields; public static final java.util.Comparator CASE_INSENSITIVE_ORDER;}